package xj.graph2d.shapes.uml;

import static javax.swing.SwingConstants.CENTER;
import static javax.swing.SwingConstants.VERTICAL;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.Label;
import xj.graph2d.TextShape;
import xj.graph2d.shapes.BoxLabel;

public class UMLUtil {

  public static final int HEADER_ROLE_NAME       = 90001;
  public static final int HEADER_ROLE_STEREOTYPE = 90002;
  public static final int HEADER_ROLE_PACKAGE    = 90003;

  public static BoxLabel makeHeader(Label name, Label stereotype) {
    return makeHeader(name, stereotype, null); 
  }

  public static BoxLabel makeHeader(Label name, 
				    Label stereotype,
				    Label pkgname) {
    BoxLabel header = new BoxLabel(VERTICAL, CENTER);
    header.setDisplayName("Header");    
    if (stereotype != null) {
      stereotype.setRole(HEADER_ROLE_STEREOTYPE);
      stereotype.setDisplayName("Stereotypes");
      String st = stereotype.getText();
      if (st != null && st.length() > 0) { 
	stereotype.setVisible(true);
      } else { 
	stereotype.setVisible(false);
      }
      stereotype.setSticky(true);
      header.addShape(stereotype);
    }
    if (name != null) {
      name.setRole(HEADER_ROLE_NAME);
      name.setDisplayName("Name");
      name.setSticky(true);
      header.addShape(name);
    }
    if (pkgname != null) { 
      pkgname.setRole(HEADER_ROLE_PACKAGE);
      pkgname.setDisplayName("Package");
      String pkg = pkgname.getText();
      if (pkg != null && pkg.length() > 0) { 
	pkgname.setVisible(true);
      } else { 
	pkgname.setVisible(false);
      }
      pkgname.setSticky(true);
      header.addShape(pkgname);
    }
    header.setSticky(true);
    header.setDetachable(false);
    header.setSelectable(false);
    header.setAcceptSubshape(false);
    header.doLayout();
    return header;
  }

  public static BoxLabel initHeader(GraphNodeBase owner, 
				    Label name,
				    Label stereotype) {
    return initHeader(owner, 
		      DrawShapeConstants.ROLE_NODE_TITLE_LABEL, 
		      name, stereotype);
  }

  public static BoxLabel initHeader(GraphNodeBase owner, 
				    int headerRole,
				    Label name, 
				    Label stereotype) {
    return initHeader(owner, headerRole, name, stereotype, null);
  }

  public static BoxLabel initHeader(GraphNodeBase owner, 
				    int headerRole,
				    Label name, 
				    Label stereotype,
				    Label pkgname) {
    if (owner != null) {
      BoxLabel header = UMLUtil.makeHeader(name, stereotype, pkgname);
      owner.setLabel(headerRole, header);
      return header;
    }
    return null;
  }

  public static BoxLabel getHeader(GraphNodeBase owner) {
    return getHeader(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
  }

  public static BoxLabel getHeader(GraphNodeBase owner, int headerRole) {
    if (owner != null) {
      return (BoxLabel) owner.getLabelShape(headerRole);
    }
    return null;
  }

  public static Label getNameShape(GraphNodeBase owner) {
    return getNameShape(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
  }

  public static Label getNameShape(GraphNodeBase owner, int headerRole) {
    if (owner != null) {
      BoxLabel header = (BoxLabel) owner.getLabelShape(headerRole);
      if (header != null) {
	Label name = (Label) header.findInRole(HEADER_ROLE_NAME);
	return name;
      }
    }
    return null;
  }

  public static String getName(GraphNodeBase owner) {
    return getName(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
  }

  public static String getName(GraphNodeBase owner, int headerRole) {
    if (owner != null) {
      Label label = getNameShape(owner, headerRole);
      if (label != null) {
	if (label instanceof TextShape) {
	  TextShape name = (TextShape) label;
	  return name.getText();
	} else {
	  int n = label.getShapeCount();
	  String name = "";
	  boolean first = true;
	  for (int i = 0; i < n; i++) {
	    DrawShape s = label.getShape(i);
	    if (s instanceof TextShape) {
	      TextShape t = (TextShape) s;
	      if (first) {
		name += t.getText();
		first = false;
	      } else {
		name += ("/" + t.getText());
	      }
	      // return name.getText();
	    }
	  }
	  return name;
	}
      }
    }
    return null;
  }

  public static void setName(GraphNodeBase owner, String name) {
    setName(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL, name);
  }

  public static void setName(GraphNodeBase owner, int headerRole, String cname) {
    //System.out.println("UMLUtil.setName()");

    if (owner != null) {
      Label label = getNameShape(owner, headerRole);
      if (label != null) {
	if (label instanceof TextShape) {
	  TextShape name = (TextShape) label;
	  name.setText(cname);
	  name.doLayout();
	} else if (label instanceof BoxLabel) {
	  int n = label.getShapeCount();
	  if (cname != null) {
	    String[] lines = cname.split("/");
	    if (lines.length == n) {
	      for (int i = 0; i < n; i++) {
		DrawShape s = label.getShape(i);
		if (s instanceof TextShape) {
		  TextShape name = (TextShape) s;
		  name.setText(lines[i]);
		  name.doLayout();
		}
	      }
	    } else {
	      setTextBox((BoxLabel) label, lines);
	    }
	  } else {
	    setTextBox((BoxLabel) label, null);
	  }
	}
	label.fitComponents();
      }
      owner.doLayout();
    }
  }

  protected static void setTextBox(BoxLabel label, String[] lines) {
    if (label != null) {
      int n = label.getShapeCount();
      TextShape proto = null;
      for (int i = 0; i < n; i++) {
	DrawShape s = label.getShape(i);
	if (s instanceof TextShape) {
	  proto = (TextShape) s;
	  break;
	}
      }
      label.removeAllShapes();
      TextShape prev = null, text;
      if (lines != null && lines.length > 0) {
	for (int i = 0; i < lines.length; i++) {
	  if (proto != null) {
	    try { 
	      text = (TextShape) proto.clone();
	    } catch (CloneNotSupportedException e) {
	      text = new TextShape();
	    }
	  } else {
	    text = new TextShape();
	  }
	  text.setText(lines[i]);
	  text.setAllowMultiLine(true);
	  text.setDetachable(false);
	  text.setScalable(false);
	  text.showCursor(true);
	  text.setMovable(true);
	  text.setSticky(false);
	  text.setAllowRotation(false);
	  if (prev != null) {
	    text.linkAfter(prev);
	  }
	  prev = text;
	  label.addShape(text);
	}
      } else {
	if (proto != null) {
	  try { 
	    text = (TextShape) proto.clone();
	    text.setText(null);
	  } catch (CloneNotSupportedException e) {
	    text = new TextShape();
	  }
	} else {
	  text = new TextShape();
	}
	text.setAllowMultiLine(false);
	text.setDetachable(false);
	text.setScalable(false);
	text.showCursor(true);
	text.setMovable(true);
	text.setSticky(false);
	text.setAllowRotation(false);
	label.addShape(text);
      }
    }
  }

  public static String getStereotypes(GraphNodeBase owner) {
    return getStereotypes(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
  }

  public static String getStereotypes(GraphNodeBase owner, int headerRole) {
    if (owner != null) {
      BoxLabel header = (BoxLabel) owner.getLabelShape(headerRole);
      if (header != null) {
	DrawShape label = header.findInRole(HEADER_ROLE_STEREOTYPE);
	if (label instanceof TextShape) {
	  TextShape stereotype = (TextShape) label;
	  String str = stereotype.getText();
	  int l = str.length();
	  if (l >= 2 && str.charAt(0) == '\u00AB' && 
	      str.charAt(l - 1) == '\u00BB') {
	    str = str.substring(1, l - 1);
	  }
	  return str;
	}
      }
    }
    return null;
  }

  public static void setStereotypes(GraphNodeBase owner, String st) {
    setStereotypes(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL, st);
  }

  public static void setStereotypes(GraphNodeBase owner, int headerRole,
				    String st) {
    if (owner != null) {
      BoxLabel header = (BoxLabel) owner.getLabelShape(headerRole);
      if (header != null) {
	DrawShape label = header.findInRole(HEADER_ROLE_STEREOTYPE);
	if (label instanceof TextShape) {
	  TextShape stereotype = (TextShape) label;
	  if (st != null && st.length() > 0) {
	    stereotype.setText(st);
	    stereotype.setVisible(true);
	  } else {
	    // remove stereotypes
	    stereotype.setText(null);
	    stereotype.setVisible(false);
	  }
	  header.doLayout();
	}
      }
    }
  }

  public static String getPackage(GraphNodeBase owner) {
    return getPackage(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
  }

  public static String getPackage(GraphNodeBase owner, int headerRole) {
    if (owner != null) {
      BoxLabel header = (BoxLabel) owner.getLabelShape(headerRole);
      if (header != null) {
	DrawShape label = header.findInRole(HEADER_ROLE_PACKAGE);
	if (label instanceof TextShape) {
	  TextShape stereotype = (TextShape) label;
	  String str = stereotype.getText();
	  return str;
	}
      }
    }
    return null;
  }

  public static void setPackage(GraphNodeBase owner, String pkgname) {
    setPackage(owner, DrawShapeConstants.ROLE_NODE_TITLE_LABEL, pkgname);
  }

  public static void setPackage(GraphNodeBase owner, 
				int headerRole,
				String pkgname) {
    if (owner != null) {
      BoxLabel header = (BoxLabel) owner.getLabelShape(headerRole);
      if (header != null) {
	DrawShape label = header.findInRole(HEADER_ROLE_PACKAGE);
	if (label instanceof TextShape) {
	  TextShape pkg = (TextShape) label;
	  if (pkgname != null && pkgname.length() > 0) {
	    pkg.setText(pkgname);
	    pkg.setVisible(true);
	  } else {
	    // remove package name
	    pkg.setText(null);
	    pkg.setVisible(false);
	  }

	  //System.out.println("UMLUtil.setPackage() @1 pkg=" + pkg); 
	  header.doLayout();
	}
      }
    }
  }

}
